package com.xyy.saas.payment.trace;

import com.alibaba.fastjson.JSON;
import com.google.common.collect.Maps;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.HttpEntity;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.concurrent.*;

/**
 * 发送微信企业信息
 */
@Component
@Slf4j
public class AlarmService {
    @Value("${alarm.switch:true}")
    private Boolean alarmSwitch;
    @Value("${tracelog.webChatWebHook:''}")
    private String webChatWebHook;
    @Value("${tracelog.webChatMobiles:''}")
    private String webChatMobiles;

    public static ThreadPoolExecutor executor = new ThreadPoolExecutor(1, 5, 10L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<>(800), r -> new Thread(r,"AlarmService"+r.hashCode()), new ThreadPoolExecutor.DiscardPolicy());//线程池饱和策略：直接丢弃

    public void alarm(DingTalkMessage msg) {
        try {
            if (!alarmSwitch) {
                return;
            }
            CompletableFuture.runAsync(() -> {
                try {
                    sendMsg(msg.toString());
                } catch (Exception e) {
                    log.error("微信告警异常" ,e);
                }
            },executor);
        } catch (Exception e) {
            log.error("微信告警异常",e);
        }
    }

    public void alarm(DingTalkMessage msg, String url, String mobiles) {
        try {
            if (!alarmSwitch) {
                return;
            }
            CompletableFuture.runAsync(() -> {
                try {
                    if (StringUtils.isBlank(url)) {
                        log.info("发送企业微信，未配置webChatWebHook，不进行发送：{}", msg.toString());
                        return;
                    }
                    String result = post(url, buildReqStr(mobiles, msg.toString()));
                    log.info("发送企业微信text消息成功{}", result);
                } catch (Exception e) {
                    log.error("发送企业微信text消息报错", e);
                }
            }, executor);
        } catch (Exception e) {
            log.error("微信告警异常", e);
        }
    }

    /**
     * 发送text消息
     * @param contents 发送内容  必填
     */
    private void sendMsg(String contents) {
        try {
            if (StringUtils.isBlank(webChatWebHook)) {
                log.info("发送企业微信，未配置webChatWebHook，不进行发送：{}", contents);
                return;
            }
            //企业微信机器人地址（配置机器人的webhook）
            String dingUrl = webChatWebHook;
            //企业微信机器人消息内容
            String content = contents;
            //组装请求内容
            String reqStr = buildReqStr(webChatMobiles, content);
            //推送消息（http请求）
            String result = post(dingUrl, reqStr);
            log.info("发送企业微信text消息成功{}", result);
        } catch (Exception e) {
            log.error("发送企业微信text消息报错{}", e);
        }
    }

    /**
     * 组装请求text报文
     */
    private String buildReqStr(String webChatMobiles, String content) {
        //消息内容
        Map<String, Object> contentMap = Maps.newHashMap();
        Map<String, Object> reqMap = Maps.newHashMap();
        reqMap.put("msgtype", "text");
        contentMap.put("content", content);
        //2.通知具体人的手机号码列表
        if (StringUtils.isNotEmpty(webChatMobiles)) {
            String[] mobiles = webChatMobiles.split(",");
            List<String> mobileList = Arrays.asList(mobiles);
            if (CollectionUtils.isNotEmpty(mobileList)) {
                contentMap.put("mentioned_mobile_list", mobileList);
            }
        } else {
            //1.是否通知所有人
            contentMap.put("mentioned_list", "");
        }
        reqMap.put("text", contentMap);
        return JSON.toJSONString(reqMap);
    }

    private static final int DEFAULT_CONNECTION_TIMEOUT = 1000 * 5; // 设置默认连接超时
    private static final int DEFAULT_SO_TIMEOUT = 1000 * 3; // 设置socket超时
    private static final String DEFAULT_CHARSET = "UTF-8"; // 设置默认通信入参编码为UTF-8
    private String post(String reqURL, String json) throws Exception {
        CloseableHttpClient httpClient = HttpClients.createDefault();
        RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(DEFAULT_SO_TIMEOUT).setConnectTimeout(DEFAULT_CONNECTION_TIMEOUT).build();
        HttpPost hp = new HttpPost(reqURL);
        String respData = null;
        CloseableHttpResponse response = null;
        try {
            StringEntity s = new StringEntity(json, "UTF-8");
            s.setContentEncoding("UTF-8");
            s.setContentType("application/json");//发送json数据需要设置contentType
            hp.setEntity(s);
            hp.setHeader("Content-Type", "application/json");
            hp.setConfig(requestConfig);
            response = httpClient.execute(hp);
            HttpEntity resEntity = response.getEntity();
            if (null != resEntity) {
                respData = EntityUtils.toString(resEntity, DEFAULT_CHARSET);
            }
        } catch (Exception e) {
            throw new Exception(e);
        } finally {
            try {
                if (response != null) {
                    response.close();
                }
                if (httpClient != null) {
                    httpClient.close();
                }
            } catch (IOException e) {
                log.error(e.getMessage(), e);
            }
        }
        return respData;
    }

}
